﻿#region License
// (c) Intergen.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using MediaWiki.Office.Model.Utilities;

namespace MediaWiki.Office.Model
{
  public class ConditionalTableStyle
  {
    private Style _style;
    private ConditionalTableStyleType _type;
    private TableProperties _tableProperties;
    private TableRowProperties _tableRowProperties;
    private TableCellProperties _tableCellProperties;
    private ParagraphProperties _paragraphProperties;
    private RunProperties _runProperties;

    public RunProperties RunProperties
    {
      get { return _runProperties; }
      set { _runProperties = value; }
    }

    public ParagraphProperties ParagraphProperties
    {
      get { return _paragraphProperties; }
      set { _paragraphProperties = value; }
    }

    public TableRowProperties TableRowProperties
    {
      get { return _tableRowProperties; }
      set { _tableRowProperties = value; }
    }

    public TableCellProperties TableCellProperties
    {
      get { return _tableCellProperties; }
      set { _tableCellProperties = value; }
    }

    public TableProperties TableProperties
    {
      get { return _tableProperties; }
      set { _tableProperties = value; }
    }

    public ConditionalTableStyleType Type
    {
      get { return _type; }
      set { _type = value; }
    }

    public ConditionalTableStyle(Style style, XElement element)
    {
      if (style == null)
        throw new ArgumentNullException("style");
      if (element == null)
        throw new ArgumentNullException("element");

      _style = style;

      XNamespace ns = Document.WordprocessingML;

      _type = XmlUtils.GetValue<ConditionalTableStyleType>(element, "type").Value;

      _tableProperties = new TableProperties(style.ParentContent, element.Element(ns + "tblPr"));
      _tableRowProperties = new TableRowProperties(style.ParentContent, element.Element(ns + "trPr"));
      _tableCellProperties = new TableCellProperties(style.ParentContent, element.Element(ns + "tcPr"));
      _paragraphProperties = new ParagraphProperties(style.ParentContent, element.Element(ns + "pPr"));
      _runProperties = new RunProperties(style.ParentContent, element.Element(ns + "rPr"));
    }

    /// <summary>
    /// Gets the conditional table style value.
    /// </summary>
    /// <typeparam name="T">The type of the value.</typeparam>
    /// <typeparam name="P">The type of the properties.</typeparam>
    /// <param name="valueGetter">The value getter. This gets the value from the desired properties on the conditional style,</param>
    /// <param name="propertiesGetter">The properties getter. This gets the desired properties object from the conditional style.</param>
    /// <param name="conditionalValue">The conditional value.</param>
    /// <param name="conditionalStyles">The conditional styles.</param>
    /// <returns></returns>
    public static T GetConditionalTableStyleValue<T, P>(Func<P, T> valueGetter,
      Func<ConditionalTableStyle, P> propertiesGetter,
      ConditionalTableStyleType conditionalValue,
      DelegateKeyedCollection<ConditionalTableStyleType, ConditionalTableStyle> conditionalStyles)
    {
      T value = default(T);

      // get a collection of all the different conditional table style types
      var conditionalTableStyleTypes = EnumUtils.EnumToArray<ConditionalTableStyleType>()
        .Where(t => t != ConditionalTableStyleType.WholeTable)
        .Reverse();

      // loop through each different conditional style and test whether it is set in the conditionalValue flags
      foreach (ConditionalTableStyleType conditionalTableStyleType in conditionalTableStyleTypes)
      {
        if ((conditionalValue & conditionalTableStyleType) == conditionalTableStyleType)
        {
          // avoid error trying to get conditional style that doesn't exist
          if (conditionalStyles.Contains(conditionalTableStyleType))
          {
            // use property getter to get wanted properties from conditional style,
            // then use value getter to get wanted value from properties
            ConditionalTableStyle conditionalStyle = conditionalStyles[conditionalTableStyleType];
            P properties = propertiesGetter(conditionalStyle);
            value = valueGetter(properties);
          }
        }

        if (value != null)
          return value;
      }

      return value;
    }
  }
}